Flyway with Spring Boot でDBマイグレーションを自動化する
よく訓練されたアップル信者、都元です。本連載もそろそろ話題が多岐に渡って来たので、第X回という運用をやめようかと思います。プロジェクトとしては順番にアップデートして成長して行きますが、そろそろ順序はどうでも良くなって来た感がありますので。
さて、システム開発をしていると大抵の場合必要になるのが、バージョンアップに伴うRDBのマイグレーションです。
私事で恐縮ですが、筆者はその昔JiemamyというRDBマイグレーションの仕組みをOSSで開発していました(残念ながら、現在はプロジェクトは完全にクローズしています)。正直Jiemamyはモノにすることができなかったのですが、現時点ではFlywayというツールに大きな可能性を感じており、筆者もプロダクション環境でこのツールを活用しています。
弊社中村による過去のご紹介記事Flywayで簡単DBマイグレーションも併せて御覧ください。
FlywayとSpring Bootの連携
Spring Bootのドキュメント 68.5.1 Execute Flyway database migrations on startup にあるように、Spring BootはFlywayとシームレスな連携を行います。どのくらいシームレスかって、まずはGitHubのdiffを御覧ください。
なんと依存ライブラリに flyway-core
を追加し、src/main/resources/db/migration/
内にSQLファイルを配置しただけです。SQLファイルの命名規則等は、Flywayのドキュメントのここを御覧ください。
これだけで何が起こるかというと、アプリケーションの起動時に、DBのマイグレーション(ここではテーブルの新規作成と初期データの投入)が起こります。マジです。
まさに黒魔術の真骨頂かもしれません。Spring Bootとはそういうフレームワークです。
試してみる berserker v10.0
とりあえずここまでのberserkerプロジェクトを実行して来た方は、ローカルのMySQLにberserker
データベースがあり、その中にテーブルがあると思います。
これは思い切って DROP DATABASE berserker;
→ CREATE DATABASE berserker;
でクリアしてしまいましょう。その上でflywayタグをチェックアウトの上、bootRunタスクを実行してみてください。(DBを削除しないと、テーブルが有るところにさらにテーブルを作ろうとしてエラーになると思います。)
$ git clone https://github.com/classmethod-aws/berserker.git $ cd berserker $ git checkout 10.0 $ ./gradlew bootRun :compileJava :processResources :classes :findMainClass :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.3.3.RELEASE) (略) 2016/04/08 11:42:21.353 [main] INFO o.f.c.internal.util.VersionPrinter:44 - Flyway 3.2.1 by Boxfuse 2016/04/08 11:42:21.625 [main] INFO o.f.c.i.dbsupport.DbSupportFactory:44 - Database: jdbc:mysql://localhost:3306/berserker?useLegacyDatetimeCode=false&serverTimezone=Universal (MySQL 5.7) 2016/04/08 11:42:21.648 [main] INFO o.f.core.internal.command.DbValidate:44 - Validated 1 migration (execution time 00:00.011s) 2016/04/08 11:42:21.685 [main] INFO o.f.c.i.m.MetaDataTableImpl:44 - Creating Metadata table: `berserker`.`schema_version` 2016/04/08 11:42:21.825 [main] INFO o.f.core.internal.command.DbMigrate:44 - Current version of schema `berserker`: << Empty Schema >> 2016/04/08 11:42:21.826 [main] INFO o.f.core.internal.command.DbMigrate:44 - Migrating schema `berserker` to version 1 - Create initial tables 2016/04/08 11:42:21.954 [main] INFO o.f.core.internal.command.DbMigrate:44 - Successfully applied 1 migration to schema `berserker` (execution time 00:00.270s). 2016/04/08 11:42:22.031 [main] INFO o.s.j.e.a.AnnotationMBeanExporter:431 - Registering beans for JMX exposure on startup 2016/04/08 11:42:22.069 [main] INFO o.a.coyote.http11.Http11NioProtocol:180 - Initializing ProtocolHandler ["http-nio-8080"] 2016/04/08 11:42:22.087 [main] INFO o.a.coyote.http11.Http11NioProtocol:180 - Starting ProtocolHandler ["http-nio-8080"] 2016/04/08 11:42:22.109 [main] INFO o.a.tomcat.util.net.NioSelectorPool:180 - Using a shared selector for servlet write/read 2016/04/08 11:42:22.129 [main] INFO o.s.b.c.e.t.TomcatEmbeddedServletContainer:162 - Tomcat started on port(s): 8080 (http) 2016/04/08 11:42:22.138 [main] INFO j.c.e.berserker.BerserkerApplication:57 - Started BerserkerApplication in 6.267 seconds (JVM running for 7.317)
(略)直後のログから、Flywayが自動的に動いているのが分かると思います。localhostのDBに対して、schema_version
というテーブルを作っています。このテーブルで、現状どこまでのスキーマ定義が適用されているのかを管理しています。初回実行時にはこのテーブルは空ですので、バージョン1から順番にSQLを適用していきます。現状バージョン1しかありませんので、そのSQLファイルが1つ実行されるだけですが。
この結果、別のシェルから下記のように、DBにアクセスできていることが確認できます。
$ curl http://localhost:8080/ User(username=miyamoto, password=$2a$10$cPnF0sq.bCPHeGuzVagOgOmbe2spT1Uh1k9LyuS0jzb5F3Lm.9kEy),User(username=yokota, password=$2a$10$nkvNPCb3Y1z/GSearD7s7OBdS9BoLBss3D4enbFQIgNJDvr0Xincm)